package com.wonders.frame.autoGeneration.support.enums;

import com.wonders.frame.autoGeneration.support.from.TableForm;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;

public enum DatasourceTypeEnum {

    MICROSOFT_SQL_SERVER("Microsoft SQL Server", Constants.sqlServerMap),
    MYSQL("MySql", Constants.mysqlMap),
    ORACLE("Oracle", Constants.oracleMap),
    DM("DM DBMS", Constants.dmMap);

    private static class Constants{
        private static final Map<String, SqlData> sqlServerMap;
        private static final Map<String, SqlData> mysqlMap;
        private static final Map<String, SqlData> oracleMap;
        private static final Map<String, SqlData> dmMap;


        static {
            sqlServerMap = new HashMap<>();
            mysqlMap = new HashMap<>();
            oracleMap = new HashMap<>();
            dmMap = new HashMap<>();


            mysqlMap.put(TableInfoSqlTypeEnum.getColumn.name(),
                    new SqlData("SELECT  column_name 'column', data_type 'type',column_comment 'comment' FROM information_schema.COLUMNS WHERE " + "table_name = ? and table_schema = ?", new MysqlGetColumnOperate()));
            mysqlMap.put(TableInfoSqlTypeEnum.getSchemas.name(),
                    new SqlData("show SCHEMAS", new MysqlGetTableOperate()));
            mysqlMap.put(TableInfoSqlTypeEnum.getTables.name(),
                    new SqlData("select table_schema 'schema',table_name 'tableName' from information_schema.TABLES where " +
                            "table_schema= ? and table_name like ?", new MysqlGetTableOperate()));

            sqlServerMap.put(TableInfoSqlTypeEnum.getColumn.name(),
                    new SqlData("select cast(a.name as varchar(500)) 'column',cast(b.name as varchar(500)) 'type'," +
                            "cast(g.value as varchar(500)) 'comment'\n" +
                            "FROM  syscolumns a left join  systypes b on  a.xusertype=b.xusertype inner join  sysobjects d \n" +
                            "on a.id=d.id  and d.xtype='U' and  d.name<>'dtproperties' left join syscomments e " +
                            "on a.cdefault=e.id left join \n" +
                            "sys.extended_properties g on a.id=G.major_id and a.colid=g.minor_id where d.name=?",
                            new SqlServerGetColumnOperate()));
            sqlServerMap.put(TableInfoSqlTypeEnum.getSchemas.name(),
                    new SqlData("", new SqlServerGetTableOperate()));
            sqlServerMap.put(TableInfoSqlTypeEnum.getTables.name(),
                    new SqlData("select name tableName from sys.tables where name like ?",
                            new SqlServerGetTableOperate()));

            oracleMap.put(TableInfoSqlTypeEnum.getColumn.name(),
                    new SqlData(" select  u1.COLUMN_NAME as \"column\",u1.DATA_TYPE as \"type\", u2.COMMENTS  as \"comment\" from \n" +
                            "user_tab_columns u1,user_col_comments u2 \n" +
                            "where u1.TABLE_NAME=u2.TABLE_NAME and u1.COLUMN_NAME=u2.COLUMN_NAME\n" +
                            "and u1.TABLE_NAME= ? ",
                            new OracleGetColumnOperate()));
            oracleMap.put(TableInfoSqlTypeEnum.getSchemas.name(),
                    new SqlData("", new OracleGetTableOperator()));
            oracleMap.put(TableInfoSqlTypeEnum.getTables.name(),
                    new SqlData("select TABLE_NAME AS \"tableName\"  from USER_TAB_COMMENTS a where a.TABLE_NAME like ? ",
                            new OracleGetTableOperator()));


            dmMap.put(TableInfoSqlTypeEnum.getColumn.name(),
                    new SqlData(" select  u1.COLUMN_NAME as \"column\",u1.DATA_TYPE as \"type\", u2.COMMENTS  as \"comment\" from \n" +
                            "user_tab_columns u1,user_col_comments u2 \n" +
                            "where u1.TABLE_NAME=u2.TABLE_NAME and u1.COLUMN_NAME=u2.COLUMN_NAME\n" +
                            "and u1.TABLE_NAME= ? ",
                            new DMGetColumnOperate()));
            dmMap.put(TableInfoSqlTypeEnum.getSchemas.name(),
                    new SqlData("", new DMGetTableOperator()));
            dmMap.put(TableInfoSqlTypeEnum.getTables.name(),
                    new SqlData("select TABLE_NAME AS \"tableName\"  from USER_TAB_COMMENTS a where a.TABLE_NAME like ? ",
                            new DMGetTableOperator()));
        }
    }


    private final String databaseType;

    private final Map<String, SqlData> sqlData;


    DatasourceTypeEnum(String databaseType,  Map<String, SqlData> sqlData){
        this.databaseType = databaseType;
        this.sqlData = sqlData;
    }

    public String getDatabaseType(){
        return this.databaseType;
    }

    public String getSql(TableInfoSqlTypeEnum type){
        return this.sqlData.get(type.name()).getSql();
    }
    public String[] getParams(TableInfoSqlTypeEnum type, TableForm form){
        return this.sqlData.get(type.name()).getParams(form);
    }

}

@Data
class SqlData {
    private String sql;
    private DatabaseOperate operate;

    SqlData(){

    }
    SqlData(String sql, DatabaseOperate operate) {
        this.sql = sql;
        this.operate =operate;
    }

    String[] getParams(TableForm form) {
        return this.operate.getParam(form);
    }

}

interface DatabaseOperate{
    String[] getParam(TableForm form);
}

class MysqlGetTableOperate implements DatabaseOperate{

    @Override
    public String[] getParam(TableForm form) {
        return new String[]{
                form.getSchema(), "%" + form.getTableName() + "%"
        };
    }
}

class MysqlGetColumnOperate implements DatabaseOperate{

    @Override
    public String[] getParam(TableForm form) {
        return new String[]{
                form.getTableName(),form.getSchema()
        };
    }
}


class SqlServerGetTableOperate implements DatabaseOperate{

    @Override
    public String[] getParam(TableForm form) {
        return new String[]{
                "%" +  form.getTableName() + "%"
        };
    }
}

class SqlServerGetColumnOperate implements DatabaseOperate{

    @Override
    public String[] getParam(TableForm form) {
        return new String[]{
                form.getTableName()
        };
    }
}


class OracleGetTableOperator implements DatabaseOperate{

    @Override
    public String[] getParam(TableForm form) {
        return new String[]{
                "%" +  form.getTableName() + "%"
        };
    }
}

class OracleGetColumnOperate implements DatabaseOperate{

    @Override
    public String[] getParam(TableForm form) {
        return new String[]{
                form.getTableName()
        };
    }
}

class DMGetTableOperator implements DatabaseOperate{

    @Override
    public String[] getParam(TableForm form) {
        return new String[]{
                "%" +  form.getTableName() + "%"
        };
    }
}

class DMGetColumnOperate implements DatabaseOperate{

    @Override
    public String[] getParam(TableForm form) {
        return new String[]{
                form.getTableName()
        };
    }
}